#include <stdio.h>
#include <errno.h>
#include <modbus.h>
#include <string.h>
#include <stdlib.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/types.h>
#include <pthread.h>
#include <sys/wait.h>
#include <sys/socket.h>
#include "cJSON.h"
#include "msg_queue_peer.h"
#include "shmem.h"

#define bool int
#define Modbus_IP "192.168.1.43"
#define Modbus_Port 502

#define MAX_NODE 128 // 最大支持数目，实际可用是127
#define STD_NODE_LEN sizeof(struct data)
#define MAX_NODE_SIZE (MAX_NODE * STD_NODE_LEN)

union val
{
    int i;   // 整形值存储空间
    bool b;  // bool类型存储空间
    float f; // 单浮点值存储空间
};

struct msg_data // 消息队列的消息类型
{
    long mtype;
    int dev_type;
    char mdata[128];
};

struct data // 共享内存
{
    int key;
    char name[32];
    long addr;
    int type;
    union val old_data;
    union val new_data;
};

modbus_t *mb;

// modbus接受指令，消息队列,线程
void *modbus_receve_thread()
{
    struct msg_data msg;
    printf("-------------------%d\n", __LINE__);
    while (1)
    {
        printf("-------------------%d\n", __LINE__);
        msg_queue_recv("topic", &msg, sizeof(msg), 1, 0);
        printf("接受指令ing....\n");
        printf("-------------------%d\n", __LINE__);
        printf("-------------------%d\n", msg.mdata[0]);
        if (msg.dev_type == 101) // 打开/关闭　车灯
        {
            modbus_write_bit(mb, 0, msg.mdata[0] - '0');
        }
        if (msg.dev_type == 102) // 上锁/解锁　车门
        {
            modbus_write_bit(mb, 1, msg.mdata[0] - '0');
        }
        if (msg.dev_type == 103) // 打开/关闭　后备箱
        {
            modbus_write_bit(mb, 2, msg.mdata[0] - '0');
        }
        if (msg.dev_type == 106) // 打开/关闭　雨刮器
        {
            modbus_write_bit(mb, 3, msg.mdata[0] - '0');
        }
    }
    pthread_exit(NULL);
}

// modbus发送数据，共享内存，线程
void *modbus_send_thread()
{
    // 初始化创建共享内存
    static int *total = NULL; // 指向共享内存头指针
    static struct data *std = NULL;
    static struct shm_param para;
    int ret = -1;
    if (shm_init(&para, "a.c", 512))
    {
        perror("shm_init err\n");
    }
    void *shmaddr = shm_getaddr(&para); // 指针指向共享内存的地址->映射
    if (NULL == shmaddr)
    {
        perror("shm getaddr err");
        return NULL;
    }
    total = (int *)shmaddr; // 前四个字节存储实际的设备数目
    std = (struct data *)(shmaddr + sizeof(int));
    uint16_t buf[1024] = {};
    uint16_t data_register[1024] = {};
    uint8_t data_coil[1024] = {};
    while (1) // 循环检测modbus salve里线圈和寄存器信息
    {
        sleep(2);
        int reg_r;
        int reg_c;
        // 读保持寄存器  功能码03
        reg_r = modbus_read_registers(mb, 0, 10, data_register);
        if (reg_r == -1)
        {
            fprintf(stderr, "Modbus read registers failed: %s\n", modbus_strerror(errno));
            continue; // 读取失败时跳过这次循环
        }
        // 读线圈   功能码01
        modbus_read_bits(mb, 0, 10, data_coil);
        if (reg_c == -1)
        {
            fprintf(stderr, "Modbus read coil failed: %s\n", modbus_strerror(errno));
            continue; // 读取失败时跳过这次循环
        }

        for (int i = 0; i < *total; i++)
        {
            if (std[i].key == 101) // 车灯开关状态
            {
                std[i].key = 101;
                std[i].new_data.i = (data_coil[0]);
            }
            if (std[i].key == 102) // 车门开关状态
            {
                std[i].key = 102;
                std[i].new_data.i = (data_coil[1]);
            }
            if (std[i].key == 103) // 后备箱开关状态
            {
                std[i].key = 103;
                std[i].new_data.i = (data_coil[2]);
            }
            if (std[i].key == 104) // 车速
            {
                std[i].key = 104;
                std[i].new_data.i = (data_register[0]);
            }
            if (std[i].key == 105) // 发动机
            {
                std[i].key = 105;
                std[i].new_data.i = (data_register[1]);
            }
            if (std[i].key == 106) // 雨刮
            {
                std[i].key = 106;
                std[i].new_data.i = (data_coil[3]);
            }
        }

        memset(data_register, 0, sizeof(data_register)); // 清空
        memset(data_coil, 0, sizeof(data_coil));
    }
    pthread_exit(NULL);
}

int main(int argc, char const *argv[])
{
    char addr[256] = {0};
	int port = 0;
    int length;
    char * data=NULL;

	FILE *file = fopen("db.json", "r");

	if (file == NULL)
	{
		perror("open file err\n");
		return -1;
	}

	printf("open file ok\n");
	fseek(file, 0, 2);
	length = ftell(file);
	fseek(file, 0, 0);

	data = malloc(length);
	fread(data, 1, length, file);
	fclose(file);
	if (data == NULL)
	{
		perror("read file err\n");
		return -1;
	}

	cJSON *json = cJSON_Parse(data);

	if (json == NULL)
	{
		perror("cJSON_Parse err\n");
		return -1;
	}
	else
		printf("cJSON_Parse ok\n");
	cJSON *mqtt_server = cJSON_GetObjectItem(json, "mb_dev");

	cJSON *server_addr = cJSON_GetObjectItem(mqtt_server, "addr");
	strcpy(addr, server_addr->valuestring);

	cJSON *server_port = cJSON_GetObjectItem(mqtt_server, "port");
	port = server_port->valueint;
    mb = modbus_new_tcp(addr, port);
    if (mb == NULL)
    {
        perror("modbus creat err");
        return -1;
    }
    if (modbus_set_slave(mb, 1) == -1)
    {
        perror("Slave machine id set err");
        return -1;
    }
    if (modbus_connect(mb) == -1)
    {
        perror("connect err");
        return -1;
    }
    pthread_t tid, tid1;
    if (pthread_create(&tid, NULL, modbus_receve_thread, NULL) != 0)
    {
        perror("phtread err");
        return -1;

    } // tid 接受指令线程
    if (pthread_create(&tid1, NULL, modbus_send_thread, NULL) != 0)
    {
        perror("phtread err");
        return -1;

    } // tid1 发送数据线程
    pthread_join(tid, NULL);
    pthread_join(tid1, NULL);
    modbus_close(mb);
    modbus_free(mb);
    mb = NULL;
    return 0;
}
